<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Word文档编辑器</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.4.17/mammoth.browser.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/html-docx-js/0.3.1/html-docx.min.js"></script>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    body {
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      line-height: 1.6;
      color: #333;
      background: linear-gradient(135deg, #f5f7fa 0%, #e4e8f0 100%);
      min-height: 100vh;
      padding: 20px;
    }
    .container {
      max-width: 1200px;
      margin: 0 auto;
      background: white;
      border-radius: 12px;
      box-shadow: 0 5px 25px rgba(0, 0, 0, 0.15);
      overflow: hidden;
    }
    header {
      background: linear-gradient(135deg, #246BFD 0%, #5089FF 100%);
      color: white;
      padding: 25px;
      text-align: center;
    }
    h1 {
      font-size: 32px;
      margin-bottom: 10px;
      font-weight: 600;
    }
    .subtitle {
      font-size: 18px;
      opacity: 0.9;
      font-weight: 300;
    }
    .main-content {
      display: flex;
      padding: 25px;
      gap: 25px;
    }
    .upload-section {
      flex: 1;
      background: #f9fafb;
      padding: 25px;
      border-radius: 10px;
      border: 2px dashed #ccc;
      text-align: center;
      transition: all 0.3s ease;
    }
    .upload-section:hover {
      border-color: #246BFD;
      background: #f0f5ff;
    }
    .editor-section {
      flex: 2;
      display: flex;
      flex-direction: column;
    }
    .editor-toolbar {
      background: #f0f2f5;
      padding: 15px;
      border-radius: 8px 8px 0 0;
      display: flex;
      gap: 12px;
      flex-wrap: wrap;
      box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
    }
    .btn {
      padding: 10px 18px;
      border: none;
      border-radius: 6px;
      cursor: pointer;
      font-weight: 500;
      transition: all 0.2s;
      display: flex;
      align-items: center;
      gap: 6px;
    }
    .btn-primary {
      background: #246BFD;
      color: white;
    }
    .btn-primary:hover {
      background: #1b5cdc;
      transform: translateY(-2px);
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    }
    .btn-success {
      background: #4CAF50;
      color: white;
    }
    .btn-success:hover {
      background: #3d8b40;
      transform: translateY(-2px);
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    }
    .editor-container {
      flex: 1;
      border: 1px solid #ddd;
      border-radius: 0 0 8px 8px;
      padding: 25px;
      min-height: 500px;
      background: white;
      overflow-y: auto;
      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
    }
    .editor {
      min-height: 450px;
      outline: none;
      padding: 15px;
      line-height: 1.8;
    }
    .editor:focus {
      border: 1px solid #246BFD;
    }
    .modal {
      display: none;
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.5);
      justify-content: center;
      align-items: center;
      z-index: 1000;
      backdrop-filter: blur(3px);
    }
    .modal.active {
      display: flex;
      animation: fadeIn 0.3s ease;
    }
    .modal-content {
      background: white;
      padding: 30px;
      border-radius: 12px;
      width: 500px;
      max-width: 90%;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
      transform: scale(0.9);
      animation: zoomIn 0.3s ease forwards;
    }
    .modal-header {
      margin-bottom: 20px;
      text-align: center;
      padding-bottom: 15px;
      border-bottom: 1px solid #eee;
    }
    .modal-header h2 {
      color: #246BFD;
      font-weight: 600;
    }
    .modal-body {
      margin-bottom: 25px;
    }
    .form-group {
      margin-bottom: 20px;
    }
    label {
      display: block;
      margin-bottom: 8px;
      font-weight: 500;
      color: #555;
    }
    input[type="text"] {
      width: 100%;
      padding: 12px;
      border: 1px solid #ddd;
      border-radius: 6px;
      font-family: inherit;
      transition: border 0.3s;
    }
    input[type="text"]:focus {
      outline: none;
      border-color: #246BFD;
      box-shadow: 0 0 0 2px rgba(36, 107, 253, 0.2);
    }
    .modal-footer {
      display: flex;
      justify-content: flex-end;
      gap: 12px;
    }
    .file-input {
      display: none;
    }
    .file-label {
      display: inline-block;
      padding: 14px 28px;
      background: #246BFD;
      color: white;
      border-radius: 6px;
      cursor: pointer;
      margin: 20px 0;
      transition: all 0.3s;
      font-weight: 500;
    }
    .file-label:hover {
      background: #1b5cdc;
      transform: translateY(-2px);
      box-shadow: 0 5px 15px rgba(36, 107, 253, 0.3);
    }
    .upload-icon {
      font-size: 52px;
      color: #246BFD;
      margin-bottom: 15px;
    }
    .instructions {
      margin-top: 25px;
      text-align: left;
      background: #fff8e1;
      padding: 18px;
      border-radius: 8px;
      border-left: 4px solid #ffc107;
    }
    .instructions h3 {
      margin-bottom: 12px;
      color: #ff9800;
      font-weight: 600;
    }
    .instructions ol {
      padding-left: 22px;
    }
    .instructions li {
      margin-bottom: 10px;
      line-height: 1.6;
    }
    .download-section {
      margin-top: 25px;
      text-align: center;
      padding-top: 20px;
      border-top: 1px solid #eee;
    }
    .status-message {
      margin-top: 15px;
      padding: 10px;
      border-radius: 6px;
      text-align: center;
      font-weight: 500;
    }
    .status-success {
      background: #e8f5e9;
      color: #4CAF50;
      border: 1px solid #c8e6c9;
    }
    .status-error {
      background: #ffebee;
      color: #f44336;
      border: 1px solid #ffcdd2;
    }
    @keyframes fadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }
    @keyframes zoomIn {
      from { transform: scale(0.9); opacity: 0; }
      to { transform: scale(1); opacity: 1; }
    }
    .cursor-indicator {
      position: absolute;
      background: #246BFD;
      width: 2px;
      height: 20px;
      animation: blink 1s infinite;
    }
    @keyframes blink {
      0%, 100% { opacity: 1; }
      50% { opacity: 0; }
    }
    @media (max-width: 900px) {
      .main-content {
        flex-direction: column;
      }
    }
  </style>
</head>
<body>
  <div id="app" class="container">
    <header>
      <h1>Word文档编辑器</h1>
      <p class="subtitle">上传、编辑、保存Word文档的一站式解决方案</p>
    </header>
    
    <div class="main-content">
      <div class="upload-section">
        <div class="upload-icon">📄</div>
        <h2>上传Word文档</h2>
        <input type="file" id="fileInput" class="file-input" @change="handleFileUpload" accept=".docx,.doc">
        <label for="fileInput" class="file-label">选择Word文档</label>
        
        <div v-if="uploadStatus" class="status-message" :class="{'status-success': uploadStatus === 'success', 'status-error': uploadStatus === 'error'}">
          {{ statusMessage }}
        </div>
        
        <div class="instructions">
          <h3>使用说明：</h3>
          <ol>
            <li>点击上方按钮上传Word文档（.docx或.doc格式）</li>
            <li>文档将显示在右侧编辑区域</li>
            <li>双击编辑区域任意位置可以插入文本</li>
            <li>使用工具栏按钮进行格式编辑</li>
            <li>编辑完成后点击"下载Word文档"保存修改</li>
          </ol>
        </div>
      </div>
      
      <div class="editor-section">
        <div class="editor-toolbar">
          <button class="btn btn-primary" @click="insertText">
            <span>📝</span> 插入文本
          </button>
          <button class="btn btn-primary" @click="formatText('bold')">
            <span>𝐁</span> 加粗
          </button>
          <button class="btn btn-primary" @click="formatText('italic')">
            <span>𝐼</span> 斜体
          </button>
          <button class="btn btn-primary" @click="formatText('underline')">
            <span>U̲</span> 下划线
          </button>
        </div>
        
        <div class="editor-container">
          <div 
            class="editor" 
            contenteditable="true" 
            ref="editor"
            @dblclick="handleDoubleClick"
            @click="updateCursorPosition"
            @keyup="updateCursorPosition"
            v-html="content"
          ></div>
        </div>
        
        <div class="download-section">
          <button class="btn btn-success" @click="exportToWord" :disabled="!content">
            <span>💾</span> 下载Word文档
          </button>
        </div>
      </div>
    </div>
    
    <div class="modal" :class="{ active: showModal }">
      <div class="modal-content">
        <div class="modal-header">
          <h2>插入文本内容</h2>
        </div>
        <div class="modal-body">
          <div class="form-group">
            <label for="textInput">请输入要插入的文本：</label>
            <input type="text" id="textInput" v-model="textToInsert" placeholder="在这里输入文本..." ref="textInput" @keyup.enter="insertTextAtCursor">
          </div>
        </div>
        <div class="modal-footer">
          <button class="btn" @click="showModal = false">取消</button>
          <button class="btn btn-primary" @click="insertTextAtCursor">插入</button>
        </div>
      </div>
    </div>
  </div>

  <script>
    new Vue({
      el: '#app',
      data: {
        content: '<p style="text-align: center; color: #246BFD; font-size: 18px;">请上传Word文档或双击此处开始编辑</p>',
        showModal: false,
        textToInsert: '',
        fileName: 'document',
        uploadStatus: '',
        statusMessage: '',
        lastCursorPosition: null,
        isDoubleClick: false
      },
      mounted() {
        // 初始化编辑器焦点
        this.$nextTick(() => {
          this.$refs.editor.focus();
        });
      },
      methods: {
        async handleFileUpload(event) {
          const file = event.target.files[0];
          if (!file) return;
          
          // 检查文件类型
          if (!file.name.match(/\.(docx|doc)$/i)) {
            this.uploadStatus = 'error';
            this.statusMessage = '请上传Word文档（.docx或.doc格式）';
            return;
          }
          
          this.fileName = file.name.replace(/\.[^/.]+$/, ""); // 移除扩展名
          
          try {
            this.uploadStatus = 'loading';
            this.statusMessage = '正在处理文档...';
            
            const arrayBuffer = await this.readFileAsArrayBuffer(file);
            const result = await mammoth.convertToHtml({ arrayBuffer });
            this.content = result.value;
            
            // 添加一些基本样式
            this.content = this.content.replace(/<p>/g, '<p style="margin-bottom: 12px;">');
            
            this.uploadStatus = 'success';
            this.statusMessage = '文档上传成功！您现在可以编辑文档了。';
            
            // 聚焦到编辑器
            this.$nextTick(() => {
              this.$refs.editor.focus();
            });
          } catch (error) {
            console.error('Error converting document:', error);
            this.uploadStatus = 'error';
            this.statusMessage = '文档转换失败，请确保上传的是有效的Word文档';
          }
        },
        
        readFileAsArrayBuffer(file) {
          return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = (e) => resolve(e.target.result);
            reader.onerror = (e) => reject(e);
            reader.readAsArrayBuffer(file);
          });
        },
        
        handleDoubleClick(event) {
          // 保存双击位置
          this.isDoubleClick = true;
          
          // 获取双击位置并设置光标
          const editor = this.$refs.editor;
          const range = document.caretRangeFromPoint(event.clientX, event.clientY);
          const selection = window.getSelection();
          
          if (range) {
            selection.removeAllRanges();
            selection.addRange(range);
            this.lastCursorPosition = range;
          }
          
          this.showDialog();
        },
        
        updateCursorPosition() {
          // 保存当前光标位置
          const selection = window.getSelection();
          if (selection.rangeCount > 0) {
            this.lastCursorPosition = selection.getRangeAt(0);
          }
        },
        
        insertText() {
          this.isDoubleClick = false;
          this.showModal = true;
          this.textToInsert = '';
          // 焦点移动到文本输入框
          this.$nextTick(() => {
            this.$refs.textInput.focus();
          });
        },
        
        showDialog() {
          this.showModal = true;
          this.textToInsert = '';
          // 焦点移动到文本输入框
          this.$nextTick(() => {
            this.$refs.textInput.focus();
          });
        },
        
        insertTextAtCursor() {
          if (!this.textToInsert.trim()) {
            alert('请输入要插入的文本');
            return;
          }
          
          const editor = this.$refs.editor;
          let selection = window.getSelection();
          
          // 恢复光标位置
          if (this.lastCursorPosition) {
            selection.removeAllRanges();
            selection.addRange(this.lastCursorPosition);
          }
          
          // 确保有有效的选择范围
          if (selection.rangeCount === 0) {
            // 如果没有选择范围，将光标放在编辑器末尾
            const range = document.createRange();
            range.selectNodeContents(editor);
            range.collapse(false);
            selection.removeAllRanges();
            selection.addRange(range);
          }
          
          // 插入文本 - 修复换行问题
          const range = selection.getRangeAt(0);
          
          // 删除选中的内容（如果有）
          range.deleteContents();
          
          // 创建文本节点并插入 - 直接插入文本，不创建额外的元素
          const textNode = document.createTextNode(this.textToInsert);
          range.insertNode(textNode);
          
          // 将光标移动到插入内容的后面
          range.setStartAfter(textNode);
          range.setEndAfter(textNode);
          selection.removeAllRanges();
          selection.addRange(range);
          
          // 更新内容
          this.content = editor.innerHTML;
          
          this.showModal = false;
          this.textToInsert = '';
          
          // 重新聚焦到编辑器
          editor.focus();
        },
        
        formatText(command) {
          document.execCommand(command, false, null);
          // 更新内容
          this.content = this.$refs.editor.innerHTML;
        },
        
        exportToWord() {
          const editor = this.$refs.editor;
          const content = editor.innerHTML;
          
          // 使用html-docx-js转换HTML为Word文档
          const converted = htmlDocx.asBlob(content, {
            orientation: 'portrait',
            margins: { top: 720, right: 720, bottom: 720, left: 720 }
          });
          
          // 保存文件
          saveAs(converted, `${this.fileName}_edited.docx`);
          
          // 显示成功消息
          this.uploadStatus = 'success';
          this.statusMessage = '文档已成功下载！';
        }
      }
    });
  </script>
</body>
</html>